// use http::Request;
// use reqwest::
use clap::Parser;

// 阅读Rust 版本指南 中文版: 自定义 Derive
// https://rustwiki.org/zh-CN/edition-guide/rust-2018/macros/custom-derive.html

#[derive(Parser, Debug)]
#[clap()]
struct CommandLineArgs {
    #[clap(short,long)]
    query : String,
}

struct Crates {
    uri: String,   // https://crates.io/api/v1/crates
    page: i32,     // page=1
    q: String,     // q=ferris_says
}

impl Crates {
    // 创建一个组织请求的链接对象
    pub fn new(query: String) -> Crates {
        Crates {
            uri: String::from("https://crates.io/api/v1/crates"), 
            page: 1, 
            q: query 
        }
    }
    // 该对像实现了函数 url 用于组织请求链接
    // https://crates.io/api/v1/crates?page=1&q=ferris_says
    fn url(&self) -> String {
        format!("{}?page={}&q={}", self.uri, self.page, self.q)
    }
}

use curl::easy::Easy;
use std::str;
// use json;

fn crates_query(url: &str)  {
    println!("- GET {}", url);

    // 请求数据 url 的数据
    let mut receive = Vec::new();
    let mut easy: Easy = Easy::new();
    easy.url(url).unwrap();
    {
        easy.useragent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36").unwrap();
        let mut transfer = easy.transfer();
        transfer.write_function(|data| {
            receive.extend_from_slice(data);
            Ok(data.len())}).unwrap();
        transfer.perform().unwrap();
    }

    // 将 Vec<u8> 转 &[u8] 
    let data = String::from_utf8(receive).unwrap();

    // 将 &[u8] 数据转为 String
    let s = str::from_utf8(data.as_bytes()).unwrap(); // 使用 unwrap
    
    // let s = match str::from_utf8(data.as_bytes()) {
    //     Ok(v) => v,
    //     Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
    // };
    // println!("result: {}", s);
    
    // 解析为 Json
    let ret = json::parse(s).unwrap(); // 使用 unwrap

    // let ret = match json::parse(s) {
    //     Ok(v) => v,
    //     Err(e) => panic!("Invalid Parser Json: {}", e),
    // };
    // println!("result: {}", ret["crates"][0]["id"]);

    // 从 json 结果集中获取一列数据
    let array = &ret["crates"];

    for i in 0..array.len() {
        println!(">>> {} = \"{}\"", &array[i]["id"],&array[i]["newest_version"]);
    }

}


fn main() {
    // println!("Hello, world!");

    // 构建一个参数解析器
    let args = CommandLineArgs::parse();
    // println!(">> Found Args: query = {}", args.query);
    
    // 构建一个搜索请求对象
    let search: Crates = Crates::new(args.query);

    // https://crates.io/api/v1/crates?page=1&per_page=10&q=ferris_says

    crates_query(search.url().as_str())
}